﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;

using SF.Serialization.Json.Converters;

namespace SF.Utilities
{
    /// <summary>
    /// 提供一组对 基础对象类型 <see cref="System.Object"/> 生成 JSON 格式字符串操作方法的扩展。
    /// </summary>
    public static partial class Serialization
    {
        private static SF.Serialization.Json.JsonSerializer _serializer;
        private static Func<SF.Serialization.Json.JsonSerializer> _serializerGenerator;


        /// <summary>
        /// 获取当前类型用于序列化 Json 对象的序列化器 <see cref="SF.Serialization.Json.JsonSerializer"/>。
        /// </summary>
        /// <remarks>在初始情况下，该序列化器由属性 <seealso cref="JsonSerializerGenerator"/> 所表示的委托函数所创建。</remarks>
        public static SF.Serialization.Json.JsonSerializer JsonSerializer
        {
            get
            {
                if (_serializer == null)
                {
                    InitializeJsonSerializer();
                }
                return _serializer;
            }
        }

        /// <summary>
        /// 初始化/重置当前类型的静态属性 <seealso cref="JsonSerializer"/> 的值。
        /// </summary>
        /// <remarks>该操作将会丢弃对当前类型的静态属性 <seealso cref="JsonSerializer"/> 值的更改。</remarks>
        public static void InitializeJsonSerializer()
        {
            _serializer = JsonSerializerGenerator();
        }


        /// <summary>
        /// 获取或设置一个具有返回值的委托函数，该函数用于获取一个 Json 序列化器 <see cref="SF.Serialization.Json.JsonSerializer"/> 对象。
        /// </summary>
        public static Func<SF.Serialization.Json.JsonSerializer> JsonSerializerGenerator
        {
            get
            {
                if (_serializerGenerator == null)
                {
                    _serializerGenerator = () => new SF.Serialization.Json.JsonSerializer();
                }
                return _serializerGenerator;
            }
            set { _serializerGenerator = value; }
        }



        /// <summary>
        /// 将一个 <see cref="System.Object"/> 对象序列化转换为 JSON 格式字符串。
        /// </summary>
        /// <param name="_this">要序列化的对象。</param>
        /// <returns>序列化的 JSON 字符串。</returns>
        /// <remarks>该方法调用 Newtonsoft.Json.dll 组件的 JsonConvert.SerializeObject 方法来执行序列化操作。</remarks>
        public static string ToJson(this object _this)
        {
            return JsonSerializer.Serialize(_this);
        }

        /// <summary>
        /// 将一个 <see cref="System.Object"/> 对象序列化转换为 JSON 格式字符串。
        /// </summary>
        /// <param name="_this">要序列化的对象。</param>
        /// <param name="formatting">定义序列化结果的输出格式。</param>
        /// <returns>序列化的 JSON 字符串。</returns>
        /// <remarks>该方法调用 Newtonsoft.Json.dll 组件的 JsonConvert.SerializeObject 方法来执行序列化操作。</remarks>
        public static string ToJson(this object _this, Formatting formatting)
        {
            return JsonSerializer.Serialize(_this, formatting);
        }

        /// <summary>
        /// 将一个 <see cref="System.Object"/> 对象序列化转换为 JSON 格式字符串。
        /// </summary>
        /// <param name="_this">要序列化的对象。</param>
        /// <param name="settings">定义序列化对象时采用的序列化设置。</param>
        /// <returns>序列化的 JSON 字符串。</returns>
        /// <remarks>该方法调用 Newtonsoft.Json.dll 组件的 JsonConvert.SerializeObject 方法来执行序列化操作。</remarks>
        public static string ToJson(this object _this, JsonSerializerSettings settings)
        {
            return JsonSerializer.Serialize(_this, settings);
        }

        /// <summary>
        /// 将一个 <see cref="System.Object"/> 对象序列化转换为 JSON 格式字符串。
        /// </summary>
        /// <param name="_this">要序列化的对象。</param>
        /// <param name="converters">定义序列化对象时的转换器集合。</param>
        /// <returns>序列化的 JSON 字符串。</returns>
        /// <remarks>该方法调用 Newtonsoft.Json.dll 组件的 JsonConvert.SerializeObject 方法来执行序列化操作。</remarks>
        public static string ToJson(this object _this, params JsonConverter[] converters)
        {
            return JsonSerializer.Serialize(_this, converters);
        }

        /// <summary>
        /// 将一个 <see cref="System.Object"/> 对象序列化转换为 JSON 格式字符串。
        /// </summary>
        /// <param name="_this">要序列化的对象。</param>
        /// <param name="formatting">定义序列化结果的输出格式。</param>
        /// <param name="settings">定义序列化对象时采用的序列化设置。</param>
        /// <returns>序列化的 JSON 字符串。</returns>
        /// <remarks>该方法调用 Newtonsoft.Json.dll 组件的 JsonConvert.SerializeObject 方法来执行序列化操作。</remarks>
        public static string ToJson(this object _this, Formatting formatting, JsonSerializerSettings settings)
        {
            return JsonSerializer.Serialize(_this, formatting, settings);
        }

        /// <summary>
        /// 将一个 <see cref="System.Object"/> 对象序列化转换为 JSON 格式字符串。
        /// </summary>
        /// <param name="_this">要序列化的对象。</param>
        /// <param name="formatting">定义序列化结果的输出格式。</param>
        /// <param name="converters">定义序列化对象时的转换器集合。</param>
        /// <returns>序列化的 JSON 字符串。</returns>
        /// <remarks>该方法调用 Newtonsoft.Json.dll 组件的 JsonConvert.SerializeObject 方法来执行序列化操作。</remarks>
        public static string ToJson(this object _this, Formatting formatting, params JsonConverter[] converters)
        {
            return JsonSerializer.Serialize(_this, formatting, converters);
        }

        /// <summary>
        /// 将一个 <see cref="System.Object"/> 对象序列化转换为 JSON 格式字符串。
        /// </summary>
        /// <param name="_this">要序列化的对象。</param>
        /// <param name="type">定义序列化对象的转换类型。</param>
        /// <param name="settings">定义序列化对象时采用的序列化设置。</param>
        /// <returns>序列化的 JSON 字符串。</returns>
        /// <remarks>该方法调用 Newtonsoft.Json.dll 组件的 JsonConvert.SerializeObject 方法来执行序列化操作。</remarks>
        public static string ToJson(this object _this, Type type, JsonSerializerSettings settings)
        {
            return JsonSerializer.Serialize(_this, type, settings);
        }

        /// <summary>
        /// 将一个 <see cref="System.Object"/> 对象序列化转换为 JSON 格式字符串。
        /// </summary>
        /// <param name="_this">要序列化的对象。</param>
        /// <param name="type">定义序列化对象的转换类型。</param>
        /// <param name="formatting">定义序列化结果的输出格式。</param>
        /// <param name="settings">定义序列化对象时采用的序列化设置。</param>
        /// <returns>序列化的 JSON 字符串。</returns>
        /// <remarks>该方法调用 Newtonsoft.Json.dll 组件的 JsonConvert.SerializeObject 方法来执行序列化操作。</remarks>
        public static string ToJson(this object _this, Type type, Formatting formatting, JsonSerializerSettings settings)
        {
            return JsonSerializer.Serialize(_this, type, formatting, settings);
        }

        /// <summary>
        /// 将json格式的字符串反序列化成指定类型的对象
        /// </summary>
        /// <typeparam name="T">指定类型</typeparam>
        /// <param name="json">要反序列化的json字符串</param>
        /// <returns></returns>
        public static T ToObject<T>(string json)
        {
            return JsonSerializer.Deserialize<T>(json);
        }

        /// <summary>
        /// 将json格式的字符串反序列化成指定类型的对象
        /// </summary>
        /// <param name="json">要反序列化的json字符串</param>
        /// <param name="type">定义反序列化对象的转换类型</param>
        /// <returns></returns>
        public static object ToObject(string json, Type type)
        {
            return JsonSerializer.Deserialize(json, type);
        }

        public static object DeserializeJsToObject(string json, Type type)
        {
            JObject jsonBody = JObject.Parse(json);
            return new JsonSerializer().Deserialize(jsonBody.CreateReader(), type);
        }

        public static T DeserializeJsToObject<T>(string json)
        {
            return (T)DeserializeJsToObject(json, typeof(T));
        }

        public static T[] DeserializeJsToArray<T>(string json)
        {
            JArray jsonRsp = JArray.Parse(json);
            IList<T> list = new List<T>();

            if (jsonRsp != null)
            {
                JsonSerializer js = new JsonSerializer();
                for (int i = 0; i < jsonRsp.Count; i++)
                {
                    object obj = js.Deserialize(jsonRsp[i].CreateReader(), typeof(T));
                    list.Add((T)obj);
                }
            }
            return list.ToArray();
        }

        public static System.Data.DataTable DeserializeJsToDataTable(string json)
        {
            JArray jsonRsp = JArray.Parse(json);
            System.Data.DataTable dt = new System.Data.DataTable();

            if (jsonRsp != null)
            {
                dt = (System.Data.DataTable)JsonConvert.DeserializeObject<System.Data.DataTable>(json);
            }
            return dt;
        }
    }

    /// <summary>
    /// 提供一组对 基础对象类型 <see cref="System.Object"/> 生成 JSON 格式字符串操作方法的扩展。
    /// 一些常用的、参数与Json.Net无直接联系的扩展。
    /// </summary>
    public static partial class Serialization
    {
        /// <summary>
        /// 将对象序列化成json格式的字符串
        /// </summary>
        /// <param name="_this">要序列化的对象</param>
        /// <param name="enumTransfer">枚举是否转换</param>
        /// <returns></returns>
        public static string ToJson(this object _this, bool enumTransfer)
        {
            return ToJson(_this, GetJsonSerializerSettings(enumTransfer, null));
        }

        /// <summary>
        /// 将对象序列化成json格式的字符串
        /// </summary>
        /// <param name="_this">要序列化的对象</param>
        /// <param name="type">日期格式化类型</param>
        /// <returns></returns>
        public static string ToJson(this object _this, DateFormatType type)
        {
            return ToJson(_this, GetJsonSerializerSettings(false, type));
        }

        /// <summary>
        /// 将对象序列化成json格式的字符串
        /// </summary>
        /// <param name="_this">要序列化的对象</param>
        /// <param name="enumTransfer">枚举是否转换</param>
        /// <param name="type">日期格式化类型</param>
        /// <returns></returns>
        public static string ToJson(this object _this, bool enumTransfer, DateFormatType type)
        {
            return ToJson(_this, GetJsonSerializerSettings(enumTransfer, type));
        }


        private static JsonSerializerSettings GetJsonSerializerSettings(bool enumTransfer, DateFormatType? type)
        {
            JsonSerializerSettings setting = new JsonSerializerSettings();
            if (enumTransfer)
            {
                //枚举值转换成字符串名字
                setting.Converters.Add(new StringEnumConverter());
            }
            if (type.HasValue && type.Value != DateFormatType.None)
            {
                setting.Converters.Add(GetDateTimeConverter(type.Value));
            }

            return setting;
        }

        private static IsoDateTimeConverter GetDateTimeConverter(DateFormatType type)
        {
            //这里使用自定义日期格式，默认是ISO8601格式
            IsoDateTimeConverter timeConverter = new IsoDateTimeConverter();
            switch (type)
            {
                case DateFormatType.yyyyMMdd: timeConverter.DateTimeFormat = "yyyy-MM-dd"; break;
                case DateFormatType.yyyyMMddHH: timeConverter.DateTimeFormat = "yyyy-MM-dd HH"; break;
                case DateFormatType.yyyyMMddHHMM: timeConverter.DateTimeFormat = "yyyy-MM-dd HH:mm"; break;
                case DateFormatType.yyyyMMddHHMMss: timeConverter.DateTimeFormat = "yyyy-MM-dd HH:mm:ss"; break;
                default: timeConverter.DateTimeFormat = "yyyy-MM-dd"; break;
            }

            return timeConverter;
        }
    }

    /// <summary>
    /// 日期格式化类型
    /// </summary>
    public enum DateFormatType
    {
        /// <summary>
        /// 不进行格式化处理
        /// </summary>
        None = 1,

        /// <summary>
        /// 以“标准年月日”进行格式化处理
        /// </summary>
        yyyyMMdd = 2,

        /// <summary>
        /// 以“年月日时”进行格式化处理
        /// </summary>
        yyyyMMddHH = 4,

        /// <summary>
        /// 以“年月日时分”进行格式化处理
        /// </summary>
        yyyyMMddHHMM = 8,

        /// <summary>
        /// 以“年月日时分秒”进行格式化处理
        /// </summary>
        yyyyMMddHHMMss = 16
    }
}
